home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / etc / bash_completion < prev    next >
Encoding:
Text File  |  2010-11-16  |  55.7 KB  |  1,642 lines

  1. #
  2. #   bash_completion - programmable completion functions for bash 3.2+
  3. #
  4. #   Copyright ┬⌐ 2006-2008, Ian Macdonald <ian@caliban.org>
  5. #             ┬⌐ 2009-2010, Bash Completion Maintainers
  6. #                     <bash-completion-devel@lists.alioth.debian.org>
  7. #
  8. #   This program is free software; you can redistribute it and/or modify
  9. #   it under the terms of the GNU General Public License as published by
  10. #   the Free Software Foundation; either version 2, or (at your option)
  11. #   any later version.
  12. #
  13. #   This program is distributed in the hope that it will be useful,
  14. #   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. #   GNU General Public License for more details.
  17. #
  18. #   You should have received a copy of the GNU General Public License
  19. #   along with this program; if not, write to the Free Software Foundation,
  20. #   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. #
  22. #   The latest version of this software can be obtained here:
  23. #
  24. #   http://bash-completion.alioth.debian.org/
  25. #
  26. #   RELEASE: 1.1
  27.  
  28. if [[ $- == *v* ]]; then
  29.     BASH_COMPLETION_ORIGINAL_V_VALUE="-v"
  30. else
  31.     BASH_COMPLETION_ORIGINAL_V_VALUE="+v"
  32. fi
  33.  
  34. if [[ -n $BASH_COMPLETION_DEBUG ]]; then
  35.     set -v
  36. else
  37.     set +v
  38. fi
  39.  
  40. # Alter the following to reflect the location of this file.
  41. #
  42. [ -n "$BASH_COMPLETION" ] || BASH_COMPLETION=/etc/bash_completion
  43. [ -n "$BASH_COMPLETION_DIR" ] || BASH_COMPLETION_DIR=/etc/bash_completion.d
  44. [ -n "$BASH_COMPLETION_COMPAT_DIR" ] || BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
  45. readonly BASH_COMPLETION BASH_COMPLETION_DIR BASH_COMPLETION_COMPAT_DIR
  46.  
  47. # Set a couple of useful vars
  48. #
  49. UNAME=$( uname -s )
  50. # strip OS type and version under Cygwin (e.g. CYGWIN_NT-5.1 => Cygwin)
  51. UNAME=${UNAME/CYGWIN_*/Cygwin}
  52.  
  53. case ${UNAME} in
  54.     Linux|GNU|GNU/*) USERLAND=GNU ;;
  55.     *) USERLAND=${UNAME} ;;
  56. esac
  57.  
  58. # Turn on extended globbing and programmable completion
  59. shopt -s extglob progcomp
  60.  
  61. # A lot of the following one-liners were taken directly from the
  62. # completion examples provided with the bash 2.04 source distribution
  63.  
  64. # Make directory commands see only directories
  65. complete -d pushd
  66.  
  67. # The following section lists completions that are redefined later
  68. # Do NOT break these over multiple lines.
  69. #
  70. # START exclude -- do NOT remove this line
  71. # bzcmp, bzdiff, bz*grep, bzless, bzmore intentionally not here, see Debian: #455510
  72. complete -f -X '!*.?(t)bz?(2)' bunzip2 bzcat pbunzip2 pbzcat
  73. complete -f -X '!*.@(zip|ZIP|[ejw]ar|[EJW]AR|exe|EXE|pk3|wsz|zargo|xpi|sxw|o[tx]t|od[fgpst]|epub)' unzip zipinfo
  74. complete -f -X '*.Z' compress znew
  75. # zcmp, zdiff, z*grep, zless, zmore intentionally not here, see Debian: #455510
  76. complete -f -X '!*.@(Z|[gGd]z|t[ag]z)' gunzip zcat unpigz
  77. complete -f -X '!*.Z' uncompress
  78. # lzcmp, lzdiff intentionally not here, see Debian: #455510
  79. complete -f -X '!*.lzma' lzcat lzegrep lzfgrep lzgrep lzless lzmore unlzma
  80. complete -f -X '!*.@(xz|lzma)' unxz xzcat
  81. complete -f -X '!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX)' ee
  82. complete -f -X '!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|GIF|JPG|JP?(E)G|TIF?(F)|PNG|P[BGP]M|BMP|X[BP]M|RLE|RGB|PCX|FITS|PM)' xv qiv
  83. complete -f -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))' gv ggv kghostview
  84. complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' xdvi
  85. complete -f -X '!*.@(dvi|DVI)?(.@(gz|Z|bz2))' kdvi
  86. complete -f -X '!*.@(dvi|DVI)' dvips dviselect dvitype dvipdf advi dvipdfm dvipdfmx
  87. complete -f -X '!*.@(pdf|PDF)' acroread gpdf xpdf
  88. complete -f -X '!*.@(?(e)ps|?(E)PS|pdf|PDF)' kpdf
  89. complete -f -X '!*.@(@(?(e)ps|?(E)PS|pdf|PDF|dvi|DVI)?(.gz|.GZ|.bz2|.BZ2)|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX|fdf|FDF)' evince
  90. complete -f -X '!*.@(okular|@(?(e|x)ps|?(E|X)PS|pdf|PDF|dvi|DVI|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX|epub|EPUB|odt|ODT|fb|FB|mobi|MOBI|g3|G3|chm|CHM|fdf|FDF)?(.?(gz|GZ|bz2|BZ2)))' okular
  91. complete -f -X '!*.@(?(e)ps|?(E)PS|pdf|PDF)' ps2pdf ps2pdf12 ps2pdf13 ps2pdf14 ps2pdfwr
  92. complete -f -X '!*.texi*' makeinfo texi2html
  93. complete -f -X '!*.@(?(la)tex|?(LA)TEX|texi|TEXI|dtx|DTX|ins|INS|ltx|LTX)' tex latex slitex jadetex pdfjadetex pdftex pdflatex texi2dvi
  94. complete -f -X '!*.@(mp3|MP3)' mpg123 mpg321 madplay
  95. complete -f -X '!*@(.@(mp?(e)g|MP?(E)G|wma|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|wmv|mp[234]|MP[234]|m4[pv]|M4[PV]|mkv|MKV|og[gmv]|OG[GMV]|t[ps]|T[PS]|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))' xine aaxine fbxine kaffeine dragon
  96. complete -f -X '!*.@(avi|asf|wmv)' aviplay
  97. complete -f -X '!*.@(rm?(j)|ra?(m)|smi?(l))' realplay
  98. complete -f -X '!*.@(mpg|mpeg|avi|mov|qt)' xanim
  99. complete -f -X '!*.@(ogg|OGG|m3u|flac|spx)' ogg123
  100. complete -f -X '!*.@(mp3|MP3|ogg|OGG|pls|m3u)' gqmpeg freeamp
  101. complete -f -X '!*.fig' xfig
  102. complete -f -X '!*.@(mid?(i)|MID?(I)|cmf|CMF)' playmidi
  103. complete -f -X '!*.@(mid?(i)|MID?(I)|rmi|RMI|rcp|RCP|[gr]36|[GR]36|g18|G18|mod|MOD|xm|XM|it|IT|x3m|X3M|s[3t]m|S[3T]M|kar|KAR)' timidity
  104. complete -f -X '!*.@(m[eo]d|M[EO]D|s[3t]m|S[3T]M|xm|XM|it|IT)' modplugplay modplug123
  105. complete -f -X '*.@(o|so|so.!(conf)|a|rpm|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MPG|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)' vi vim gvim rvim view rview rgvim rgview gview emacs xemacs sxemacs kate kwrite
  106. complete -f -X '!*.@([eE][xX][eE]?(.[sS][oO])|[cC][oO][mM]|[sS][cC][rR])' wine
  107. complete -f -X '!*.@(zip|ZIP|z|Z|gz|GZ|tgz|TGZ)' bzme
  108. # konqueror not here on purpose, it's more than a web/html browser
  109. complete -f -X '!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))' netscape mozilla lynx opera galeon dillo elinks amaya firefox mozilla-firefox iceweasel google-chrome chromium-browser epiphany
  110. complete -f -X '!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|odt|ott|odm)' oowriter
  111. complete -f -X '!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|odp|otp)' ooimpress
  112. complete -f -X '!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|ods|ots)' oocalc
  113. complete -f -X '!*.@(sxd|std|sda|sdd|odg|otg)' oodraw
  114. complete -f -X '!*.@(sxm|smf|mml|odf)' oomath
  115. complete -f -X '!*.odb' oobase
  116. complete -f -X '!*.rpm' rpm2cpio
  117. complete -f -X '!*.s@(qlite?(3)|?(3)db)' sqlite3
  118. complete -f -X '!*.aux' bibtex
  119. complete -f -X '!*.po' poedit gtranslator kbabel lokalize
  120. complete -f -X '!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])' harbour gharbour hbpp
  121. complete -f -X '!*.[Hh][Rr][Bb]' hbrun
  122. complete -f -X '!*.ly' lilypond ly2dvi
  123. complete -f -X '!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))' cdiff
  124. complete -f -X '!*.@(dif?(f)|?(d)patch)' kompare
  125. complete -f -X '!*.lyx' lyx
  126. # FINISH exclude -- do not remove this line
  127.  
  128. # start of section containing compspecs that can be handled within bash
  129.  
  130. # user commands see only users
  131. complete -u su passwd write chfn groups slay w sux
  132.  
  133. # bg completes with stopped jobs
  134. complete -A stopped -P '"%' -S '"' bg
  135.  
  136. # other job commands
  137. complete -j -P '"%' -S '"' fg jobs disown
  138.  
  139. # readonly and unset complete with shell variables
  140. complete -v readonly unset
  141.  
  142. # set completes with set options
  143. complete -A setopt set
  144.  
  145. # shopt completes with shopt options
  146. complete -A shopt shopt
  147.  
  148. # helptopics
  149. complete -A helptopic help
  150.  
  151. # unalias completes with aliases
  152. complete -a unalias
  153.  
  154. # bind completes with readline bindings (make this more intelligent)
  155. complete -A binding bind
  156.  
  157. # type and which complete on commands
  158. complete -c command type which
  159.  
  160. # builtin completes on builtins
  161. complete -b builtin
  162.  
  163. # start of section containing completion functions called by other functions
  164.  
  165. # This function checks whether we have a given program on the system.
  166. # No need for bulky functions in memory if we don't.
  167. #
  168. have()
  169. {
  170.     unset -v have
  171.     # Completions for system administrator commands are installed as well in
  172.     # case completion is attempted via `sudo command ...'.
  173.     PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&
  174.     have="yes"
  175. }
  176.  
  177. # This function checks whether a given readline variable
  178. # is `on'.
  179. #
  180. _rl_enabled()
  181. {
  182.     [[ "$( bind -v )" = *$1+([[:space:]])on* ]]
  183. }
  184.  
  185. # This function shell-quotes the argument
  186. quote()
  187. {
  188.     echo \'${1//\'/\'\\\'\'}\' #'# Help vim syntax highlighting
  189. }
  190.  
  191. # @see _quote_readline_by_ref()
  192. quote_readline()
  193. {
  194.     local quoted
  195.     _quote_readline_by_ref "$1" ret
  196.     printf %s "$ret"
  197. } # quote_readline()
  198.  
  199.  
  200. # This function shell-dequotes the argument
  201. dequote()
  202. {
  203.     eval echo "$1" 2> /dev/null
  204. }
  205.  
  206.  
  207. # Assign variable one scope above the caller
  208. # Usage: local "$1" && _upvar $1 "value(s)"
  209. # Param: $1  Variable name to assign value to
  210. # Param: $*  Value(s) to assign.  If multiple values, an array is
  211. #            assigned, otherwise a single value is assigned.
  212. # NOTE: For assigning multiple variables, use '_upvars'.  Do NOT
  213. #       use multiple '_upvar' calls, since one '_upvar' call might
  214. #       reassign a variable to be used by another '_upvar' call.
  215. # See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
  216. _upvar() {
  217.     if unset -v "$1"; then           # Unset & validate varname
  218.         if (( $# == 2 )); then
  219.             eval $1=\"\$2\"          # Return single value
  220.         else
  221.             eval $1=\(\"\${@:2}\"\)  # Return array
  222.         fi
  223.     fi
  224. }
  225.  
  226.  
  227. # Assign variables one scope above the caller
  228. # Usage: local varname [varname ...] && 
  229. #        _upvars [-v varname value] | [-aN varname [value ...]] ...
  230. # Available OPTIONS:
  231. #     -aN  Assign next N values to varname as array
  232. #     -v   Assign single value to varname
  233. # Return: 1 if error occurs
  234. # See: http://fvue.nl/wiki/Bash:_Passing_variables_by_reference
  235. _upvars() {
  236.     if ! (( $# )); then
  237.         echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname"\
  238.             "value] | [-aN varname [value ...]] ..." 1>&2
  239.         return 2
  240.     fi
  241.     while (( $# )); do
  242.         case $1 in
  243.             -a*)
  244.                 # Error checking
  245.                 [[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1': missing"\
  246.                     "number specifier" 1>&2; return 1; }
  247.                 printf %d "${1#-a}" &> /dev/null || { echo "bash:"\
  248.                     "${FUNCNAME[0]}: \`$1': invalid number specifier" 1>&2
  249.                     return 1; }
  250.                 # Assign array of -aN elements
  251.                 [[ "$2" ]] && unset -v "$2" && eval $2=\(\"\${@:3:${1#-a}}\"\) && 
  252.                 shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:"\
  253.                     "\`$1${2+ }$2': missing argument(s)" 1>&2; return 1; }
  254.                 ;;
  255.             -v)
  256.                 # Assign single value
  257.                 [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" &&
  258.                 shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\
  259.                 "argument(s)" 1>&2; return 1; }
  260.                 ;;
  261.             *)
  262.                 echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2
  263.                 return 1 ;;
  264.         esac
  265.     done
  266. }
  267.  
  268.  
  269. # Reassemble command line words, excluding specified characters from the
  270. # list of word completion separators (COMP_WORDBREAKS).
  271. # @param $1 chars  Characters out of $COMP_WORDBREAKS which should
  272. #     NOT be considered word breaks. This is useful for things like scp where
  273. #     we want to return host:path and not only path, so we would pass the
  274. #     colon (:) as $1 here.
  275. # @param $2 words  Name of variable to return words to
  276. # @param $3 cword  Name of variable to return cword to
  277. #
  278. __reassemble_comp_words_by_ref() {
  279.     local exclude i j ref
  280.     # Exclude word separator characters?
  281.     if [[ $1 ]]; then
  282.         # Yes, exclude word separator characters;
  283.         # Exclude only those characters, which were really included
  284.         exclude="${1//[^$COMP_WORDBREAKS]}"
  285.     fi
  286.         
  287.     # Default to cword unchanged
  288.     eval $3=$COMP_CWORD
  289.     # Are characters excluded which were former included?
  290.     if [[ $exclude ]]; then
  291.         # Yes, list of word completion separators has shrunk;
  292.         # Re-assemble words to complete
  293.         for (( i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
  294.             # Is current word not word 0 (the command itself) and is word not
  295.             # empty and is word made up of just word separator characters to be
  296.             # excluded?
  297.             while [[ $i -gt 0 && ${COMP_WORDS[$i]} && 
  298.                 ${COMP_WORDS[$i]//[^$exclude]} == ${COMP_WORDS[$i]} 
  299.             ]]; do
  300.                 [ $j -ge 2 ] && ((j--))
  301.                 # Append word separator to current word
  302.                 ref="$2[$j]"
  303.                 eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
  304.                 # Indicate new cword
  305.                 [ $i = $COMP_CWORD ] && eval $3=$j
  306.                 # Indicate next word if available, else end *both* while and for loop
  307.                 (( $i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2
  308.             done
  309.             # Append word to current word
  310.             ref="$2[$j]"
  311.             eval $2[$j]=\${!ref}\${COMP_WORDS[i]}
  312.             # Indicate new cword
  313.             [ $i = $COMP_CWORD ] && [[ ${COMP_WORDS[i]} ]] && eval $3=$j
  314.         done
  315.     else
  316.         # No, list of word completions separators hasn't changed;
  317.         eval $2=\( \"\${COMP_WORDS[@]}\" \)
  318.     fi
  319. } # __reassemble_comp_words_by_ref()
  320.  
  321.  
  322. # @param $1 exclude  Characters out of $COMP_WORDBREAKS which should NOT be
  323. #     considered word breaks. This is useful for things like scp where
  324. #     we want to return host:path and not only path, so we would pass the
  325. #     colon (:) as $1 in this case.  Bash-3 doesn't do word splitting, so this
  326. #     ensures we get the same word on both bash-3 and bash-4.
  327. # @param $2 words  Name of variable to return words to
  328. # @param $3 cword  Name of variable to return cword to
  329. # @param $4 cur  Name of variable to return current word to complete to
  330. # @see ___get_cword_at_cursor_by_ref()
  331. __get_cword_at_cursor_by_ref() {
  332.     local cword words=()
  333.     __reassemble_comp_words_by_ref "$1" words cword
  334.  
  335.     local i cur2
  336.     local cur="$COMP_LINE"
  337.     local index="$COMP_POINT"
  338.     for (( i = 0; i <= cword; ++i )); do
  339.         while [[
  340.             # Current word fits in $cur?
  341.             "${#cur}" -ge ${#words[i]} &&
  342.             # $cur doesn't match cword?
  343.             "${cur:0:${#words[i]}}" != "${words[i]}"
  344.         ]]; do
  345.             # Strip first character
  346.             cur="${cur:1}"
  347.             # Decrease cursor position
  348.             ((index--))
  349.         done
  350.  
  351.         # Does found word matches cword?
  352.         if [[ "$i" -lt "$cword" ]]; then
  353.             # No, cword lies further;
  354.             local old_size="${#cur}"
  355.             cur="${cur#${words[i]}}"
  356.             local new_size="${#cur}"
  357.             index=$(( index - old_size + new_size ))
  358.         fi
  359.     done
  360.  
  361.     if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
  362.         # We messed up. At least return the whole word so things keep working
  363.         cur2=${words[cword]}
  364.     else
  365.         cur2=${cur:0:$index}
  366.     fi
  367.  
  368.     local "$2" "$3" "$4" && 
  369.         _upvars -a${#words[@]} $2 "${words[@]}" -v $3 "$cword" -v $4 "$cur2"
  370. }
  371.  
  372.  
  373. # Get the word to complete and optional previous words.
  374. # This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
  375. # where the user is completing in the middle of a word.
  376. # (For example, if the line is "ls foobar",
  377. # and the cursor is here -------->   ^
  378. # Also one is able to cross over possible wordbreak characters.
  379. # Usage: _get_comp_words_by_ref [OPTIONS] [VARNAMES]
  380. # Available VARNAMES:
  381. #     cur         Return cur via $cur
  382. #     prev        Return prev via $prev
  383. #     words       Return words via $words
  384. #     cword       Return cword via $cword
  385. #
  386. # Available OPTIONS:
  387. #     -n EXCLUDE  Characters out of $COMP_WORDBREAKS which should NOT be 
  388. #                 considered word breaks. This is useful for things like scp
  389. #                 where we want to return host:path and not only path, so we
  390. #                 would pass the colon (:) as -n option in this case.  Bash-3
  391. #                 doesn't do word splitting, so this ensures we get the same
  392. #                 word on both bash-3 and bash-4.
  393. #     -c VARNAME  Return cur via $VARNAME
  394. #     -p VARNAME  Return prev via $VARNAME
  395. #     -w VARNAME  Return words via $VARNAME
  396. #     -i VARNAME  Return cword via $VARNAME
  397. #
  398. # Example usage:
  399. #
  400. #    $ _get_comp_words_by_ref -n : cur prev
  401. #
  402. _get_comp_words_by_ref()
  403. {
  404.     local exclude flag i OPTIND=1
  405.     local cur cword words=()
  406.     local upargs=() upvars=() vcur vcword vprev vwords
  407.  
  408.     while getopts "c:i:n:p:w:" flag "$@"; do
  409.         case $flag in
  410.             c) vcur=$OPTARG ;;
  411.             i) vcword=$OPTARG ;;
  412.             n) exclude=$OPTARG ;;
  413.             p) vprev=$OPTARG ;;
  414.             w) vwords=$OPTARG ;;
  415.         esac
  416.     done
  417.     while [[ $# -ge $OPTIND ]]; do 
  418.         case ${!OPTIND} in
  419.             cur)   vcur=cur ;;
  420.             prev)  vprev=prev ;;
  421.             cword) vcword=cword ;;
  422.             words) vwords=words ;;
  423.             *) echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" \
  424.                 1>&2; return 1
  425.         esac
  426.         let "OPTIND += 1"
  427.     done
  428.  
  429.     __get_cword_at_cursor_by_ref "$exclude" words cword cur
  430.  
  431.     [[ $vcur   ]] && { upvars+=("$vcur"  ); upargs+=(-v $vcur   "$cur"  ); }
  432.     [[ $vcword ]] && { upvars+=("$vcword"); upargs+=(-v $vcword "$cword"); }
  433.     [[ $vprev  ]] && { upvars+=("$vprev" ); upargs+=(-v $vprev 
  434.         "${words[cword - 1]}"); }
  435.     [[ $vwords ]] && { upvars+=("$vwords"); upargs+=(-a${#words[@]} $vwords
  436.         "${words[@]}"); }
  437.  
  438.     (( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
  439. }
  440.  
  441.  
  442. # Get the word to complete.
  443. # This is nicer than ${COMP_WORDS[$COMP_CWORD]}, since it handles cases
  444. # where the user is completing in the middle of a word.
  445. # (For example, if the line is "ls foobar",
  446. # and the cursor is here -------->   ^
  447. # @param $1 string  Characters out of $COMP_WORDBREAKS which should NOT be
  448. #     considered word breaks. This is useful for things like scp where
  449. #     we want to return host:path and not only path, so we would pass the
  450. #     colon (:) as $1 in this case.  Bash-3 doesn't do word splitting, so this
  451. #     ensures we get the same word on both bash-3 and bash-4.
  452. # @param $2 integer  Index number of word to return, negatively offset to the
  453. #     current word (default is 0, previous is 1), respecting the exclusions
  454. #     given at $1.  For example, `_get_cword "=:" 1' returns the word left of
  455. #     the current word, respecting the exclusions "=:".
  456. # @deprecated  Use `_get_comp_words_by_ref cur' instead
  457. # @see _get_comp_words_by_ref()
  458. _get_cword()
  459. {
  460.     local LC_CTYPE=C
  461.     local cword words
  462.     __reassemble_comp_words_by_ref "$1" words cword
  463.  
  464.     # return previous word offset by $2
  465.     if [[ ${2//[^0-9]/} ]]; then
  466.         printf "%s" "${words[cword-$2]}"
  467.     elif [[ "${#words[cword]}" -eq 0 ]] || [[ "$COMP_POINT" == "${#COMP_LINE}" ]]; then
  468.         printf "%s" "${words[cword]}"
  469.     else
  470.         local i
  471.         local cur="$COMP_LINE"
  472.         local index="$COMP_POINT"
  473.         for (( i = 0; i <= cword; ++i )); do
  474.             while [[
  475.                 # Current word fits in $cur?
  476.                 "${#cur}" -ge ${#words[i]} &&
  477.                 # $cur doesn't match cword?
  478.                 "${cur:0:${#words[i]}}" != "${words[i]}"
  479.             ]]; do
  480.                 # Strip first character
  481.                 cur="${cur:1}"
  482.                 # Decrease cursor position
  483.                 ((index--))
  484.             done
  485.  
  486.             # Does found word matches cword?
  487.             if [[ "$i" -lt "$cword" ]]; then
  488.                 # No, cword lies further;
  489.                 local old_size="${#cur}"
  490.                 cur="${cur#${words[i]}}"
  491.                 local new_size="${#cur}"
  492.                 index=$(( index - old_size + new_size ))
  493.             fi
  494.         done
  495.  
  496.         if [[ "${words[cword]:0:${#cur}}" != "$cur" ]]; then
  497.             # We messed up! At least return the whole word so things
  498.             # keep working
  499.             printf "%s" "${words[cword]}"
  500.         else
  501.             printf "%s" "${cur:0:$index}"
  502.         fi
  503.     fi
  504. } # _get_cword()
  505.  
  506.  
  507. # Get word previous to the current word.
  508. # This is a good alternative to `prev=${COMP_WORDS[COMP_CWORD-1]}' because bash4
  509. # will properly return the previous word with respect to any given exclusions to
  510. # COMP_WORDBREAKS.
  511. # @deprecated  Use `_get_comp_words_by_ref cur prev' instead
  512. # @see _get_comp_words_by_ref()
  513. #
  514. _get_pword() 
  515. {
  516.     if [ $COMP_CWORD -ge 1 ]; then
  517.         _get_cword "${@:-}" 1;
  518.     fi
  519. }
  520.  
  521.  
  522. # If the word-to-complete contains a colon (:), left-trim COMPREPLY items with
  523. # word-to-complete.
  524. # On bash-3, and bash-4 with a colon in COMP_WORDBREAKS, words containing
  525. # colons are always completed as entire words if the word to complete contains
  526. # a colon.  This function fixes this, by removing the colon-containing-prefix
  527. # from COMPREPLY items.
  528. # The preferred solution is to remove the colon (:) from COMP_WORDBREAKS in
  529. # your .bashrc:
  530. #
  531. #    # Remove colon (:) from list of word completion separators
  532. #    COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
  533. #
  534. # See also: Bash FAQ - E13) Why does filename completion misbehave if a colon
  535. # appears in the filename? - http://tiswww.case.edu/php/chet/bash/FAQ
  536. # @param $1 current word to complete (cur)
  537. # @modifies global array $COMPREPLY
  538. #
  539. __ltrim_colon_completions() {
  540.     # If word-to-complete contains a colon,
  541.     # and bash-version < 4,
  542.     # or bash-version >= 4 and COMP_WORDBREAKS contains a colon
  543.     if [[
  544.         "$1" == *:* && (
  545.             ${BASH_VERSINFO[0]} -lt 4 || 
  546.             (${BASH_VERSINFO[0]} -ge 4 && "$COMP_WORDBREAKS" == *:*) 
  547.         )
  548.     ]]; then
  549.         # Remove colon-word prefix from COMPREPLY items
  550.         local colon_word=${1%${1##*:}}
  551.         local i=${#COMPREPLY[*]}
  552.         while [ $((--i)) -ge 0 ]; do
  553.             COMPREPLY[$i]=${COMPREPLY[$i]#"$colon_word"}
  554.         done
  555.     fi
  556. } # __ltrim_colon_completions()
  557.  
  558.  
  559. # This function quotes the argument in a way so that readline dequoting
  560. # results in the original argument.  This is necessary for at least
  561. # `compgen' which requires its arguments quoted/escaped:
  562. #
  563. #     $ ls "a'b/"
  564. #     c
  565. #     $ compgen -f "a'b/"       # Wrong, doesn't return output
  566. #     $ compgen -f "a\'b/"      # Good (bash-4)
  567. #     a\'b/c
  568. #     $ compgen -f "a\\\\\'b/"  # Good (bash-3)
  569. #     a\'b/c
  570. #
  571. # See also: http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00155.html
  572. # @param $1  Argument to quote
  573. # @param $2  Name of variable to return result to
  574. _quote_readline_by_ref()
  575. {
  576.     if [[ ${1:0:1} == "'" ]]; then
  577.         # Quote word, leaving out first character
  578.         printf -v $2 %q "${1:1}"
  579.         if [[ ${BASH_VERSINFO[0]} -le 3 ]]; then
  580.             # Double-quote word on bash-3
  581.             printf -v $2 %q ${!2}
  582.         fi
  583.     elif [[ ${BASH_VERSINFO[0]} -le 3 && ${1:0:1} == '"' ]]; then
  584.         printf -v $2 %q "${1:1}"
  585.     else
  586.         printf -v $2 %q "$1"
  587.     fi
  588.  
  589.     # If result becomes quoted like this: $'string', re-evaluate in order to
  590.     # drop the additional quoting.  See also: http://www.mail-archive.com/
  591.     # bash-completion-devel@lists.alioth.debian.org/msg01942.html
  592.     [[ ${!2:0:1} == '$' ]] && eval $2=${!2}
  593. } # _quote_readline_by_ref()
  594.  
  595.  
  596. # This function performs file and directory completion. It's better than
  597. # simply using 'compgen -f', because it honours spaces in filenames.
  598. # @param $1  If `-d', complete only on directories.  Otherwise filter/pick only
  599. #            completions with `.$1' as file extension.
  600. #
  601. _filedir()
  602. {
  603.     local i IFS=$'\t\n' xspec
  604.  
  605.     __expand_tilde_by_ref cur
  606.  
  607.     local -a toks
  608.     local quoted tmp
  609.  
  610.     _quote_readline_by_ref "$cur" quoted
  611.     toks=( ${toks[@]-} $(
  612.         compgen -d -- "$quoted" | {
  613.             while read -r tmp; do
  614.                 # TODO: I have removed a "[ -n $tmp ] &&" before 'printf ..',
  615.                 #       and everything works again. If this bug suddenly
  616.                 #       appears again (i.e. "cd /b<TAB>" becomes "cd /"),
  617.                 #       remember to check for other similar conditionals (here
  618.                 #       and _filedir_xspec()). --David
  619.                 printf '%s\n' $tmp
  620.             done
  621.         }
  622.     ))
  623.  
  624.     # On bash-3, special characters need to be escaped extra.  This is
  625.     # unless the first character is a single quote (').  If the single
  626.     # quote appears further down the string, bash default completion also
  627.     # fails, e.g.:
  628.     #
  629.     #     $ ls 'a&b/'
  630.     #     f
  631.     #     $ foo 'a&b/<TAB>  # Becomes: foo 'a&b/f'
  632.     #     $ foo a'&b/<TAB>  # Nothing happens
  633.     #
  634.     if [[ "$1" != -d ]]; then
  635.         xspec=${1:+"!*.$1"}
  636.         if [[ ${cur:0:1} == "'" && ${BASH_VERSINFO[0]} -ge 4 ]]; then
  637.             toks=( ${toks[@]-} $(
  638.                 eval compgen -f -X \"\$xspec\" -- $quoted
  639.             ) )
  640.         else
  641.             toks=( ${toks[@]-} $(
  642.                 compgen -f -X "$xspec" -- $quoted
  643.             ) )
  644.         fi
  645.         if [ ${#toks[@]} -ne 0 ]; then
  646.             # If `compopt' is available, set `-o filenames'
  647.             compopt &>/dev/null && compopt -o filenames ||
  648.             # No, `compopt' isn't available;
  649.             # Is `-o filenames' set?
  650.             [[ (
  651.                 ${COMP_WORDS[0]} && 
  652.                 "$(complete -p ${COMP_WORDS[0]})" == *"-o filenames"*
  653.             ) ]] || {
  654.                 # No, `-o filenames' isn't set;
  655.                 # Emulate `-o filenames'
  656.                 # NOTE: A side-effect of emulating `-o filenames' is that
  657.                 #       backslash escape characters are visible within the list
  658.                 #       of presented completions, e.g.  the completions look
  659.                 #       like:
  660.                 #
  661.                 #           $ foo a<TAB>
  662.                 #           a\ b/  a\$b/
  663.                 #
  664.                 #       whereas with `-o filenames' active the completions look
  665.                 #       like:
  666.                 #
  667.                 #           $ ls a<TAB>
  668.                 #           a b/  a$b/
  669.                 #
  670.                 for ((i=0; i < ${#toks[@]}; i++)); do
  671.                     # If directory exists, append slash (/)
  672.                     if [[ ${cur:0:1} != "'" ]]; then
  673.                         [[ -d ${toks[i]} ]] && toks[i]="${toks[i]}"/
  674.                         if [[ ${cur:0:1} == '"' ]]; then
  675.                             toks[i]=${toks[i]//\\/\\\\}
  676.                             toks[i]=${toks[i]//\"/\\\"}
  677.                             toks[i]=${toks[i]//\$/\\\$}
  678.                         else
  679.                             toks[i]=$(printf %q ${toks[i]})
  680.                         fi
  681.                     fi
  682.                 done
  683.             }
  684.         fi
  685.     fi
  686.  
  687.     COMPREPLY=( "${COMPREPLY[@]}" "${toks[@]}" )
  688. } # _filedir()
  689.  
  690.  
  691. # This function splits $cur=--foo=bar into $prev=--foo, $cur=bar, making it
  692. # easier to support both "--foo bar" and "--foo=bar" style completions.
  693. # Returns 0 if current option was split, 1 otherwise.
  694. #
  695. _split_longopt()
  696. {
  697.     if [[ "$cur" == --?*=* ]]; then
  698.         # Cut also backslash before '=' in case it ended up there
  699.         # for some reason.
  700.         prev="${cur%%?(\\)=*}"
  701.         cur="${cur#*=}"
  702.         return 0
  703.     fi
  704.  
  705.     return 1
  706. }
  707.  
  708. # This function tries to parse the output of $command --help
  709. #
  710. _parse_help() {
  711.     local cmd
  712.     cmd=$1
  713.     $cmd --help 2>&1 | command grep -- "^[[:space:]]*-" | tr "," " " | \
  714.         awk '{print $1; if ($2 ~ /-.*/) { print $2 } }' | sed -e "s:=.*::g"
  715. }
  716.  
  717. # This function completes on signal names
  718. #
  719. _signals()
  720. {
  721.     local i
  722.  
  723.     # standard signal completion is rather braindead, so we need
  724.     # to hack around to get what we want here, which is to
  725.     # complete on a dash, followed by the signal name minus
  726.     # the SIG prefix
  727.     COMPREPLY=( $( compgen -A signal SIG${cur#-} ))
  728.     for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  729.         COMPREPLY[i]=-${COMPREPLY[i]#SIG}
  730.     done
  731. }
  732.  
  733. # This function completes on known mac addresses
  734. #
  735. _mac_addresses()
  736. {
  737.     local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}'
  738.     local PATH="$PATH:/sbin:/usr/sbin"
  739.  
  740.     # Local interfaces (Linux only?)
  741.     COMPREPLY=( "${COMPREPLY[@]}" $( ifconfig -a 2>/dev/null | sed -ne \
  742.         "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" ) )
  743.  
  744.     # ARP cache
  745.     COMPREPLY=( "${COMPREPLY[@]}" $( arp -an 2>/dev/null | sed -ne \
  746.         "s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne \
  747.         "s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p" ) )
  748.  
  749.     COMPREPLY=( $( compgen -W '${COMPREPLY[@]}' -- "$cur" ) )
  750.     __ltrim_colon_completions "$cur"
  751. }
  752.  
  753. # This function completes on configured network interfaces
  754. #
  755. _configured_interfaces()
  756. {
  757.     if [ -f /etc/debian_version ]; then
  758.         # Debian system
  759.         COMPREPLY=( $( compgen -W "$( sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p'\
  760.             /etc/network/interfaces )" -- "$cur" ) )
  761.     elif [ -f /etc/SuSE-release ]; then
  762.         # SuSE system
  763.         COMPREPLY=( $( compgen -W "$( printf '%s\n' \
  764.             /etc/sysconfig/network/ifcfg-* | \
  765.             sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
  766.     elif [ -f /etc/pld-release ]; then
  767.         # PLD Linux
  768.         COMPREPLY=( $( compgen -W "$( command ls -B \
  769.             /etc/sysconfig/interfaces | \
  770.             sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
  771.     else
  772.         # Assume Red Hat
  773.         COMPREPLY=( $( compgen -W "$( printf '%s\n' \
  774.             /etc/sysconfig/network-scripts/ifcfg-* | \
  775.             sed -ne 's|.*ifcfg-\(.*\)|\1|p' )" -- "$cur" ) )
  776.     fi
  777. }
  778.  
  779. # This function completes on available kernels
  780. #
  781. _kernel_versions()
  782. {
  783.     COMPREPLY=( $( compgen -W '$( command ls /lib/modules )' -- "$cur" ) )
  784. }
  785.  
  786. # This function completes on all available network interfaces
  787. # -a: restrict to active interfaces only
  788. # -w: restrict to wireless interfaces only
  789. #
  790. _available_interfaces()
  791. {
  792.     local cmd
  793.  
  794.     if [ "${1:-}" = -w ]; then
  795.         cmd="iwconfig"
  796.     elif [ "${1:-}" = -a ]; then
  797.         cmd="ifconfig"
  798.     else
  799.         cmd="ifconfig -a"
  800.     fi
  801.  
  802.     COMPREPLY=( $( eval PATH="$PATH:/sbin" $cmd 2>/dev/null | \
  803.         awk '/^[^ \t]/ { print $1 }' ) )
  804.     COMPREPLY=( $( compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur" ) )
  805. }
  806.  
  807.  
  808. # Expand variable starting with tilde (~)
  809. # Only the first portion of the variable from the tilde up to the first slash
  810. # (~../) is expanded.  The remainder of the variable, containing for example
  811. # a dollar sign variable ($) or asterisk (*) is not expanded.
  812. # Example usage:
  813. #
  814. #    $ v="~"; __expand_tilde_by_ref v; echo "$v"
  815. #
  816. # Example output:
  817. #
  818. #       v                  output
  819. #    --------         ----------------
  820. #    ~                /home/user
  821. #    ~foo/bar         /home/foo/bar
  822. #    ~foo/$HOME       /home/foo/$HOME
  823. #    ~foo/a  b        /home/foo/a  b
  824. #    ~foo/*           /home/foo/*
  825. #  
  826. # @param $1  Name of variable (not the value of the variable) to expand
  827. __expand_tilde_by_ref() {
  828.     # Does $1 start with tilde (~)?
  829.     if [ "${!1:0:1}" = "~" ]; then
  830.         # Does $1 contain slash (/)?
  831.         if [ "${!1}" != "${!1//\/}" ]; then
  832.             # Yes, $1 contains slash;
  833.             # 1: Remove * including and after first slash (/), i.e. "~a/b"
  834.             #    becomes "~a".  Double quotes allow eval.
  835.             # 2: Remove * before the first slash (/), i.e. "~a/b"
  836.             #    becomes "b".  Single quotes prevent eval.
  837.             #                          +-----1----+ +---2----+
  838.             eval $1="${!1/%\/*}"/'${!1#*/}'
  839.         else 
  840.             # No, $1 doesn't contain slash
  841.             eval $1="${!1}"
  842.         fi
  843.     fi
  844. } # __expand_tilde_by_ref()
  845.  
  846.  
  847. # This function expands tildes in pathnames
  848. #
  849. _expand()
  850. {
  851.     # FIXME: Why was this here?
  852.     #[ "$cur" != "${cur%\\}" ] && cur="$cur\\"
  853.  
  854.     # Expand ~username type directory specifications.  We want to expand
  855.     # ~foo/... to /home/foo/... to avoid problems when $cur starting with
  856.     # a tilde is fed to commands and ending up quoted instead of expanded.
  857.  
  858.     if [[ "$cur" == \~*/* ]]; then
  859.         eval cur=$cur
  860.     elif [[ "$cur" == \~* ]]; then
  861.         cur=${cur#\~}
  862.         COMPREPLY=( $( compgen -P '~' -u "$cur" ) )
  863.         [ ${#COMPREPLY[@]} -eq 1 ] && eval COMPREPLY[0]=${COMPREPLY[0]}
  864.         return ${#COMPREPLY[@]}
  865.     fi
  866. }
  867.  
  868. # This function completes on process IDs.
  869. # AIX and Solaris ps prefers X/Open syntax.
  870. [[ $UNAME == SunOS || $UNAME == AIX ]] &&
  871. _pids()
  872. {
  873.     COMPREPLY=( $( compgen -W '$( command ps -efo pid | sed 1d )' -- "$cur" ))
  874. } ||
  875. _pids()
  876. {
  877.     COMPREPLY=( $( compgen -W '$( command ps axo pid= )' -- "$cur" ) )
  878. }
  879.  
  880. # This function completes on process group IDs.
  881. # AIX and SunOS prefer X/Open, all else should be BSD.
  882. [[ $UNAME == SunOS || $UNAME == AIX ]] &&
  883. _pgids()
  884. {
  885.     COMPREPLY=( $( compgen -W '$( command ps -efo pgid | sed 1d )' -- "$cur" ))
  886. } ||
  887. _pgids()
  888. {
  889.     COMPREPLY=( $( compgen -W '$( command ps axo pgid= )' -- "$cur" ))
  890. }
  891.  
  892. # This function completes on process names.
  893. # AIX and SunOS prefer X/Open, all else should be BSD.
  894. [[ $UNAME == SunOS || $UNAME == AIX ]] &&
  895. _pnames()
  896. {
  897.     COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps -efo comm | \
  898.         sed -e 1d -e "s:.*/::" -e "s/^-//" | sort -u )' -- "$cur" ) )
  899. } ||
  900. _pnames()
  901. {
  902.     # FIXME: completes "[kblockd/0]" to "0". Previously it was completed
  903.     # to "kblockd" which isn't correct either. "kblockd/0" would be
  904.     # arguably most correct, but killall from psmisc 22 treats arguments
  905.     # containing "/" specially unless -r is given so that wouldn't quite
  906.     # work either. Perhaps it'd be best to not complete these to anything
  907.     # for now.
  908.     # Not using "ps axo comm" because under some Linux kernels, it
  909.     # truncates command names (see e.g. http://bugs.debian.org/497540#19)
  910.     COMPREPLY=( $( compgen -X '<defunct>' -W '$( command ps axo command= | \
  911.         sed -e "s/ .*//" -e "s:.*/::" -e "s/:$//" -e "s/^[[(-]//" \
  912.             -e "s/[])]$//" | sort -u )' -- "$cur" ) )
  913. }
  914.  
  915. # This function completes on user IDs
  916. #
  917. _uids()
  918. {
  919.     if type getent &>/dev/null; then
  920.         COMPREPLY=( $( compgen -W '$( getent passwd | cut -d: -f3 )' -- "$cur" ) )
  921.     elif type perl &>/dev/null; then
  922.         COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"' )' -- "$cur" ) )
  923.     else
  924.         # make do with /etc/passwd
  925.         COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/passwd )' -- "$cur" ) )
  926.     fi
  927. }
  928.  
  929. # This function completes on group IDs
  930. #
  931. _gids()
  932. {
  933.     if type getent &>/dev/null; then
  934.         COMPREPLY=( $( compgen -W '$( getent group | cut -d: -f3 )' \
  935.             -- "$cur" ) )
  936.     elif type perl &>/dev/null; then
  937.         COMPREPLY=( $( compgen -W '$( perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"' )' -- "$cur" ) )
  938.     else
  939.         # make do with /etc/group
  940.         COMPREPLY=( $( compgen -W '$( cut -d: -f3 /etc/group )' -- "$cur" ) )
  941.     fi
  942. }
  943.  
  944. # This function completes on services
  945. #
  946. _services()
  947. {
  948.     local sysvdir famdir
  949.     [ -d /etc/rc.d/init.d ] && sysvdir=/etc/rc.d/init.d || sysvdir=/etc/init.d
  950.     famdir=/etc/xinetd.d
  951.     COMPREPLY=( $( printf '%s\n' \
  952.         $sysvdir/!(*.rpm@(orig|new|save)|*~|functions) ) )
  953.  
  954.     if [ -d $famdir ]; then
  955.         COMPREPLY=( "${COMPREPLY[@]}" $( printf '%s\n' \
  956.             $famdir/!(*.rpm@(orig|new|save)|*~) ) )
  957.     fi
  958.  
  959.     COMPREPLY=( $( compgen -W '${COMPREPLY[@]#@($sysvdir|$famdir)/}' -- "$cur" ) )
  960. }
  961.  
  962. # This function completes on modules
  963. #
  964. _modules()
  965. {
  966.     local modpath
  967.     modpath=/lib/modules/$1
  968.     COMPREPLY=( $( compgen -W "$( command ls -R $modpath | \
  969.         sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.gz\)\{0,1\}$/\1/p' )" -- "$cur" ) )
  970. }
  971.  
  972. # This function completes on installed modules
  973. #
  974. _installed_modules()
  975. {
  976.     COMPREPLY=( $( compgen -W "$( PATH="$PATH:/sbin" lsmod | \
  977.         awk '{if (NR != 1) print $1}' )" -- "$1" ) )
  978. }
  979.  
  980. # This function completes on user or user:group format; as for chown and cpio.
  981. #
  982. # The : must be added manually; it will only complete usernames initially.
  983. # The legacy user.group format is not supported.
  984. #
  985. # It assumes compopt -o filenames; but doesn't touch it.
  986. _usergroup()
  987. {
  988.     local IFS=$'\n'
  989.     if [[ $cur = *\\\\* || $cur = *:*:* ]]; then
  990.         # Give up early on if something seems horribly wrong.
  991.         return
  992.     elif [[ $cur = *\\:* ]]; then
  993.         # Completing group after 'user\:gr<TAB>'.
  994.         # Reply with a list of groups prefixed with 'user:', readline will
  995.         # escape to the colon.
  996.         local prefix
  997.         prefix=${cur%%*([^:])}
  998.         prefix=${prefix//\\}
  999.         COMPREPLY=( $( compgen -P "$prefix" -g -- "${cur#*[:]}" ) )
  1000.     elif [[ $cur = *:* ]]; then
  1001.         # Completing group after 'user:gr<TAB>'.
  1002.         # Reply with a list of unprefixed groups since readline with split on :
  1003.         # and only replace the 'gr' part
  1004.         COMPREPLY=( $( compgen -g -- "${cur#*:}" ) )
  1005.     else
  1006.         # Completing a partial 'usernam<TAB>'.
  1007.         #
  1008.         # Don't suffix with a : because readline will escape it and add a
  1009.         # slash. It's better to complete into 'chown username ' than 'chown
  1010.         # username\:'.
  1011.         COMPREPLY=( $( compgen -u -- "$cur" ) )
  1012.     fi
  1013. }
  1014.  
  1015. # This function completes on valid shells
  1016. #
  1017. _shells()
  1018. {
  1019.     COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W \
  1020.         '$( command grep "^[[:space:]]*/" /etc/shells 2>/dev/null )' \
  1021.         -- "$cur" ) )
  1022. }
  1023.  
  1024. # This function completes on valid filesystem types
  1025. #
  1026. _fstypes()
  1027. {
  1028.     local fss
  1029.  
  1030.     if [ -e /proc/filesystems ] ; then
  1031.         # Linux
  1032.         fss="$( cut -d$'\t' -f2 /proc/filesystems )
  1033.              $( awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null )"
  1034.     else
  1035.         # Generic
  1036.         fss="$( awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null )
  1037.              $( awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null )
  1038.              $( awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null )
  1039.              $( awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null )
  1040.              $( [ -d /etc/fs ] && command ls /etc/fs )"
  1041.     fi
  1042.  
  1043.     [ -n "$fss" ] && \
  1044.         COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$fss" -- "$cur" ) )
  1045. }
  1046.  
  1047. # Get real command.
  1048. # - arg: $1  Command
  1049. # - stdout:  Filename of command in PATH with possible symbolic links resolved.
  1050. #            Empty string if command not found.
  1051. # - return:  True (0) if command found, False (> 0) if not.
  1052. _realcommand()
  1053. {
  1054.     type -P "$1" > /dev/null && {
  1055.         if type -p realpath > /dev/null; then
  1056.             realpath "$(type -P "$1")"
  1057.         elif type -p readlink > /dev/null; then
  1058.             readlink -f "$(type -P "$1")"
  1059.         else
  1060.             type -P "$1"
  1061.         fi
  1062.     }
  1063. }
  1064.  
  1065. # This function returns the first arugment, excluding options
  1066. # @param $1 chars  Characters out of $COMP_WORDBREAKS which should
  1067. #     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
  1068. _get_first_arg()
  1069. {
  1070.     local i
  1071.  
  1072.     arg=
  1073.     for (( i=1; i < COMP_CWORD; i++ )); do
  1074.         if [[ "${COMP_WORDS[i]}" != -* ]]; then
  1075.             arg=${COMP_WORDS[i]}
  1076.             break
  1077.         fi
  1078.     done
  1079. }
  1080.  
  1081.  
  1082. # This function counts the number of args, excluding options
  1083. # @param $1 chars  Characters out of $COMP_WORDBREAKS which should
  1084. #     NOT be considered word breaks. See __reassemble_comp_words_by_ref.
  1085. _count_args()
  1086. {
  1087.     local i cword words
  1088.     __reassemble_comp_words_by_ref "$1" words cword
  1089.  
  1090.     args=1
  1091.     for i in "${words[@]:1:cword-1}"; do
  1092.         [[ "$i" != -* ]] && args=$(($args+1))
  1093.     done
  1094. }
  1095.  
  1096. # This function completes on PCI IDs
  1097. #
  1098. _pci_ids()
  1099. {
  1100.     COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
  1101.         "$( PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur" ) )
  1102. }
  1103.  
  1104. # This function completes on USB IDs
  1105. #
  1106. _usb_ids()
  1107. {
  1108.     COMPREPLY=( ${COMPREPLY[@]:-} $( compgen -W \
  1109.         "$( PATH="$PATH:/sbin" lsusb | awk '{print $6}' )" -- "$cur" ) )
  1110. }
  1111.  
  1112. # CD device names
  1113. _cd_devices()
  1114. {
  1115.     COMPREPLY=( "${COMPREPLY[@]}"
  1116.         $( compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}" ) )
  1117. }
  1118.  
  1119. # DVD device names
  1120. _dvd_devices()
  1121. {
  1122.     COMPREPLY=( "${COMPREPLY[@]}"
  1123.         $( compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}" ) )
  1124. }
  1125.  
  1126. # start of section containing completion functions for external programs
  1127.  
  1128. # a little help for FreeBSD ports users
  1129. [ $UNAME = FreeBSD ] && complete -W 'index search fetch fetch-list extract \
  1130.     patch configure build install reinstall deinstall clean clean-depends \
  1131.     kernel buildworld' make
  1132.  
  1133. # This function provides simple user@host completion
  1134. #
  1135. _user_at_host() {
  1136.     local cur
  1137.  
  1138.     COMPREPLY=()
  1139.     _get_comp_words_by_ref -n : cur
  1140.  
  1141.     if [[ $cur == *@* ]]; then
  1142.         _known_hosts_real "$cur"
  1143.     else
  1144.         COMPREPLY=( $( compgen -u -- "$cur" ) )
  1145.     fi
  1146.  
  1147.     return 0
  1148. }
  1149. shopt -u hostcomplete && complete -F _user_at_host -o nospace talk ytalk finger
  1150.  
  1151. # NOTE: Using this function as a helper function is deprecated.  Use
  1152. #       `_known_hosts_real' instead.
  1153. _known_hosts()
  1154. {
  1155.     local options
  1156.     COMPREPLY=()
  1157.  
  1158.     # NOTE: Using `_known_hosts' as a helper function and passing options
  1159.     #       to `_known_hosts' is deprecated: Use `_known_hosts_real' instead.
  1160.     [[ "$1" == -a || "$2" == -a ]] && options=-a
  1161.     [[ "$1" == -c || "$2" == -c ]] && options="$options -c"
  1162.     _known_hosts_real $options "$(_get_cword :)"
  1163. } # _known_hosts()
  1164.  
  1165. # Helper function for completing _known_hosts.
  1166. # This function performs host completion based on ssh's config and known_hosts
  1167. # files, as well as hostnames reported by avahi-browse.  Also hosts from
  1168. # HOSTFILE (compgen -A hostname) are added, unless
  1169. # COMP_KNOWN_HOSTS_WITH_HOSTFILE is set to an empty value.
  1170. # Usage: _known_hosts_real [OPTIONS] CWORD
  1171. # Options:  -a             Use aliases
  1172. #           -c             Use `:' suffix
  1173. #           -F configfile  Use `configfile' for configuration settings
  1174. #           -p PREFIX      Use PREFIX
  1175. # Return: Completions, starting with CWORD, are added to COMPREPLY[]
  1176. _known_hosts_real()
  1177. {
  1178.     local configfile flag prefix
  1179.     local cur curd awkcur user suffix aliases i host
  1180.     local -a kh khd config
  1181.  
  1182.     local OPTIND=1
  1183.     while getopts "acF:p:" flag "$@"; do
  1184.         case $flag in
  1185.             a) aliases='yes' ;;
  1186.             c) suffix=':' ;;
  1187.             F) configfile=$OPTARG ;;
  1188.             p) prefix=$OPTARG ;;
  1189.         esac
  1190.     done
  1191.     [ $# -lt $OPTIND ] && echo "error: $FUNCNAME: missing mandatory argument CWORD"
  1192.     cur=${!OPTIND}; let "OPTIND += 1"
  1193.     [ $# -ge $OPTIND ] && echo "error: $FUNCNAME("$@"): unprocessed arguments:"\
  1194.     $(while [ $# -ge $OPTIND ]; do printf '%s\n' ${!OPTIND}; shift; done)
  1195.  
  1196.     [[ $cur == *@* ]] && user=${cur%@*}@ && cur=${cur#*@}
  1197.     kh=()
  1198.  
  1199.     # ssh config files
  1200.     if [ -n "$configfile" ]; then
  1201.         [ -r "$configfile" ] &&
  1202.         config=( "${config[@]}" "$configfile" )
  1203.     else
  1204.         [ -r /etc/ssh/ssh_config ] &&
  1205.         config=( "${config[@]}" "/etc/ssh/ssh_config" )
  1206.         [ -r "${HOME}/.ssh/config" ] &&
  1207.         config=( "${config[@]}" "${HOME}/.ssh/config" )
  1208.         [ -r "${HOME}/.ssh2/config" ] &&
  1209.         config=( "${config[@]}" "${HOME}/.ssh2/config" )
  1210.     fi
  1211.  
  1212.     # Known hosts files from configs
  1213.     if [ ${#config[@]} -gt 0 ]; then
  1214.         local OIFS=$IFS IFS=$'\n'
  1215.         local -a tmpkh
  1216.         # expand paths (if present) to global and user known hosts files
  1217.         # TODO(?): try to make known hosts files with more than one consecutive
  1218.         #          spaces in their name work (watch out for ~ expansion
  1219.         #          breakage! Alioth#311595)
  1220.         tmpkh=( $( awk 'sub("^[ \t]*([Gg][Ll][Oo][Bb][Aa][Ll]|[Uu][Ss][Ee][Rr])[Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee][ \t]+", "") { print $0 }' "${config[@]}" | sort -u ) )
  1221.         for i in "${tmpkh[@]}"; do
  1222.             # Remove possible quotes
  1223.             i=${i//\"}
  1224.             # Eval/expand possible `~' or `~user'
  1225.             __expand_tilde_by_ref i
  1226.             [ -r "$i" ] && kh=( "${kh[@]}" "$i" )
  1227.         done
  1228.         IFS=$OIFS
  1229.     fi
  1230.  
  1231.     # Global known_hosts files
  1232.     if [ -z "$configfile" ]; then
  1233.         [ -r /etc/ssh/ssh_known_hosts ] &&
  1234.         kh=( "${kh[@]}" /etc/ssh/ssh_known_hosts )
  1235.         [ -r /etc/ssh/ssh_known_hosts2 ] &&
  1236.         kh=( "${kh[@]}" /etc/ssh/ssh_known_hosts2 )
  1237.         [ -r /etc/known_hosts ] &&
  1238.         kh=( "${kh[@]}" /etc/known_hosts )
  1239.         [ -r /etc/known_hosts2 ] &&
  1240.         kh=( "${kh[@]}" /etc/known_hosts2 )
  1241.         [ -d /etc/ssh2/knownhosts ] &&
  1242.         khd=( "${khd[@]}" /etc/ssh2/knownhosts/*pub )
  1243.     fi
  1244.  
  1245.     # User known_hosts files
  1246.     if [ -z "$configfile" ]; then
  1247.         [ -r ~/.ssh/known_hosts ] &&
  1248.         kh=( "${kh[@]}" ~/.ssh/known_hosts )
  1249.         [ -r ~/.ssh/known_hosts2 ] &&
  1250.         kh=( "${kh[@]}" ~/.ssh/known_hosts2 )
  1251.         [ -d ~/.ssh2/hostkeys ] &&
  1252.         khd=( "${khd[@]}" ~/.ssh2/hostkeys/*pub )
  1253.     fi
  1254.  
  1255.     # If we have known_hosts files to use
  1256.     if [[ ${#kh[@]} -gt 0 || ${#khd[@]} -gt 0 ]]; then
  1257.         # Escape slashes and dots in paths for awk
  1258.         awkcur=${cur//\//\\\/}
  1259.         awkcur=${awkcur//\./\\\.}
  1260.         curd=$awkcur
  1261.  
  1262.         if [[ "$awkcur" == [0-9]*.* ]]; then
  1263.             # Digits followed by a dot - just search for that
  1264.             awkcur="^$awkcur.*"
  1265.         elif [[ "$awkcur" == [0-9]* ]]; then
  1266.             # Digits followed by no dot - search for digits followed
  1267.             # by a dot
  1268.             awkcur="^$awkcur.*\."
  1269.         elif [ -z "$awkcur" ]; then
  1270.             # A blank - search for a dot or an alpha character
  1271.             awkcur="[a-z.]"
  1272.         else
  1273.             awkcur="^$awkcur"
  1274.         fi
  1275.  
  1276.         if [ ${#kh[@]} -gt 0 ]; then
  1277.             # FS needs to look for a comma separated list
  1278.             COMPREPLY=( "${COMPREPLY[@]}" $( awk 'BEGIN {FS=","}
  1279.             /^\s*[^|\#]/ {for (i=1; i<=2; ++i) { \
  1280.             gsub(" .*$", "", $i); \
  1281.             gsub("[\\[\\]]", "", $i); \
  1282.             gsub(":[0-9]+$", "", $i); \
  1283.             if ($i ~ /'"$awkcur"'/) {print $i} \
  1284.             }}' "${kh[@]}" 2>/dev/null ) )
  1285.         fi
  1286.         if [ ${#khd[@]} -gt 0 ]; then
  1287.             # Needs to look for files called
  1288.             # .../.ssh2/key_22_<hostname>.pub
  1289.             # dont fork any processes, because in a cluster environment,
  1290.             # there can be hundreds of hostkeys
  1291.             for i in "${khd[@]}" ; do
  1292.                 if [[ "$i" == *key_22_$curd*.pub && -r "$i" ]]; then
  1293.                     host=${i/#*key_22_/}
  1294.                     host=${host/%.pub/}
  1295.                     COMPREPLY=( "${COMPREPLY[@]}" $host )
  1296.                 fi
  1297.             done
  1298.         fi
  1299.  
  1300.         # apply suffix and prefix
  1301.         for (( i=0; i < ${#COMPREPLY[@]}; i++ )); do
  1302.             COMPREPLY[i]=$prefix$user${COMPREPLY[i]}$suffix
  1303.         done
  1304.     fi
  1305.  
  1306.     # append any available aliases from config files
  1307.     if [[ ${#config[@]} -gt 0 && -n "$aliases" ]]; then
  1308.         local hosts=$( sed -ne 's/^[ \t]*[Hh][Oo][Ss][Tt]\([Nn][Aa][Mm][Ee]\)\{0,1\}['"$'\t '"']\{1,\}\([^#*?]*\)\(#.*\)\{0,1\}$/\2/p' "${config[@]}" )
  1309.         COMPREPLY=( "${COMPREPLY[@]}" $( compgen  -P "$prefix$user" \
  1310.             -S "$suffix" -W "$hosts" -- "$cur" ) )
  1311.     fi
  1312.  
  1313.     # Add hosts reported by avahi-browse, if it's available.
  1314.     # The original call to avahi-browse also had "-k", to avoid lookups into
  1315.     # avahi's services DB. We don't need the name of the service, and if it
  1316.     # contains ";", it may mistify the result. But on Gentoo (at least),
  1317.     # -k isn't available (even if mentioned in the manpage), so...
  1318.     if type avahi-browse >&/dev/null; then
  1319.         COMPREPLY=( "${COMPREPLY[@]}" $( \
  1320.             compgen -P "$prefix$user" -S "$suffix" -W \
  1321.             "$( avahi-browse -cpr _workstation._tcp 2>/dev/null | \
  1322.                  awk -F';' '/^=/ { print $7 }' | sort -u )" -- "$cur" ) )
  1323.     fi
  1324.  
  1325.     # Add results of normal hostname completion, unless
  1326.     # `COMP_KNOWN_HOSTS_WITH_HOSTFILE' is set to an empty value.
  1327.     if [ -n "${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1}" ]; then
  1328.         COMPREPLY=( "${COMPREPLY[@]}"
  1329.             $( compgen -A hostname -P "$prefix$user" -S "$suffix" -- "$cur" ) )
  1330.     fi
  1331.  
  1332.     __ltrim_colon_completions "$prefix$user$cur"
  1333.  
  1334.     return 0
  1335. } # _known_hosts_real()
  1336. complete -F _known_hosts traceroute traceroute6 tracepath tracepath6 ping \
  1337.     ping6 fping fping6 telnet host nslookup rsh rlogin ftp dig mtr \
  1338.     ssh-installkeys showmount
  1339.  
  1340. # This meta-cd function observes the CDPATH variable, so that cd additionally
  1341. # completes on directories under those specified in CDPATH.
  1342. #
  1343. _cd()
  1344. {
  1345.     local cur IFS=$'\t\n' i j k
  1346.     _get_comp_words_by_ref cur
  1347.  
  1348.     # try to allow variable completion
  1349.     if [[ "$cur" == ?(\\)\$* ]]; then
  1350.         COMPREPLY=( $( compgen -v -P '$' -- "${cur#?(\\)$}" ) )
  1351.         return 0
  1352.     fi
  1353.  
  1354.     # Enable -o filenames option, see Debian bug #272660
  1355.     compgen -f /non-existing-dir/ >/dev/null
  1356.  
  1357.     # Use standard dir completion if no CDPATH or parameter starts with /,
  1358.     # ./ or ../
  1359.     if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
  1360.         _filedir -d
  1361.         return 0
  1362.     fi
  1363.  
  1364.     local -r mark_dirs=$(_rl_enabled mark-directories && echo y)
  1365.     local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y)
  1366.  
  1367.     # we have a CDPATH, so loop on its contents
  1368.     for i in ${CDPATH//:/$'\t'}; do
  1369.         # create an array of matched subdirs
  1370.         k="${#COMPREPLY[@]}"
  1371.         for j in $( compgen -d $i/$cur ); do
  1372.             if [[ ( $mark_symdirs && -h $j || $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
  1373.                 j="${j}/"
  1374.             fi
  1375.             COMPREPLY[k++]=${j#$i/}
  1376.         done
  1377.     done
  1378.  
  1379.     _filedir -d
  1380.  
  1381.     if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
  1382.         i=${COMPREPLY[0]}
  1383.         if [[ "$i" == "$cur" && $i != "*/" ]]; then
  1384.             COMPREPLY[0]="${i}/"
  1385.         fi
  1386.     fi
  1387.  
  1388.     return 0
  1389. }
  1390. if shopt -q cdable_vars; then
  1391.     complete -v -F _cd -o nospace cd
  1392. else
  1393.     complete -F _cd -o nospace cd
  1394. fi
  1395.  
  1396. # a wrapper method for the next one, when the offset is unknown
  1397. _command()
  1398. {
  1399.     local offset i
  1400.  
  1401.     # find actual offset, as position of the first non-option
  1402.     offset=1
  1403.     for (( i=1; i <= COMP_CWORD; i++ )); do
  1404.         if [[ "${COMP_WORDS[i]}" != -* ]]; then
  1405.             offset=$i
  1406.             break
  1407.         fi
  1408.     done
  1409.     _command_offset $offset
  1410. }
  1411.  
  1412. # A meta-command completion function for commands like sudo(8), which need to
  1413. # first complete on a command, then complete according to that command's own
  1414. # completion definition - currently not quite foolproof (e.g. mount and umount
  1415. # don't work properly), but still quite useful.
  1416. #
  1417. _command_offset()
  1418. {
  1419.     local cur func cline cspec noglob cmd i char_offset word_offset \
  1420.         _COMMAND_FUNC _COMMAND_FUNC_ARGS
  1421.  
  1422.     word_offset=$1
  1423.  
  1424.     # rewrite current completion context before invoking
  1425.     # actual command completion
  1426.  
  1427.     # find new first word position, then
  1428.     # rewrite COMP_LINE and adjust COMP_POINT
  1429.     local first_word=${COMP_WORDS[$word_offset]}
  1430.     for (( i=0; i <= ${#COMP_LINE}; i++ )); do
  1431.         if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
  1432.             char_offset=$i
  1433.             break
  1434.         fi
  1435.     done
  1436.     COMP_LINE=${COMP_LINE:$char_offset}
  1437.     COMP_POINT=$(( COMP_POINT - $char_offset ))
  1438.  
  1439.     # shift COMP_WORDS elements and adjust COMP_CWORD
  1440.     for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
  1441.         COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
  1442.     done
  1443.     for (( i; i <= COMP_CWORD; i++ )); do
  1444.         unset COMP_WORDS[i];
  1445.     done
  1446.     COMP_CWORD=$(( $COMP_CWORD - $word_offset ))
  1447.  
  1448.     COMPREPLY=()
  1449.     _get_comp_words_by_ref cur
  1450.  
  1451.     if [[ $COMP_CWORD -eq 0 ]]; then
  1452.         COMPREPLY=( $( compgen -c -- "$cur" ) )
  1453.     else
  1454.         cmd=${COMP_WORDS[0]}
  1455.         if complete -p $cmd &>/dev/null; then
  1456.             cspec=$( complete -p $cmd )
  1457.             if [ "${cspec#* -F }" != "$cspec" ]; then
  1458.                 # complete -F <function>
  1459.  
  1460.                 # get function name
  1461.                 func=${cspec#*-F }
  1462.                 func=${func%% *}
  1463.  
  1464.                 if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
  1465.                     $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
  1466.                 else
  1467.                     $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
  1468.                 fi
  1469.  
  1470.                 # remove any \: generated by a command that doesn't
  1471.                 # default to filenames or dirnames (e.g. sudo chown)
  1472.                 # FIXME: I'm pretty sure this does not work!
  1473.                 if [ "${cspec#*-o }" != "$cspec" ]; then
  1474.                     cspec=${cspec#*-o }
  1475.                     cspec=${cspec%% *}
  1476.                     if [[ "$cspec" != @(dir|file)names ]]; then
  1477.                         COMPREPLY=("${COMPREPLY[@]//\\\\:/:}")
  1478.                     fi
  1479.                 fi
  1480.             elif [ -n "$cspec" ]; then
  1481.                 cspec=${cspec#complete};
  1482.                 cspec=${cspec%%$cmd};
  1483.                 COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
  1484.             fi
  1485.         fi
  1486.     fi
  1487.  
  1488.     [ ${#COMPREPLY[@]} -eq 0 ] && _filedir
  1489. }
  1490. complete -F _command -o filenames nohup exec nice eval time ltrace then \
  1491.     else do vsound command xargs tsocks aoss padsp
  1492.  
  1493. _root_command()
  1494. {
  1495.     local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin
  1496.     _command $1 $2 $3
  1497. }
  1498. complete -F _root_command -o filenames sudo fakeroot really gksudo gksu kdesudo
  1499.  
  1500. _longopt()
  1501. {
  1502.     local cur prev
  1503.  
  1504.     _get_comp_words_by_ref cur prev
  1505.  
  1506.     if _split_longopt; then
  1507.         case "$prev" in
  1508.             *[Dd][Ii][Rr]*)
  1509.                 _filedir -d
  1510.                 ;;
  1511.             *[Ff][Ii][Ll][Ee]*)
  1512.                 _filedir
  1513.                 ;;
  1514.         esac
  1515.         return 0
  1516.     fi
  1517.  
  1518.     if [[ "$cur" == -* ]]; then
  1519.         COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | \
  1520.             sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}\).*/\1/p' | sort -u )" \
  1521.             -- "$cur" ) )
  1522.     elif [[ "$1" == rmdir ]]; then
  1523.         _filedir -d
  1524.     else
  1525.         _filedir
  1526.     fi
  1527. }
  1528. # makeinfo and texi2dvi are defined elsewhere.
  1529. for i in a2ps autoconf automake bc gprof ld nm objcopy objdump readelf strip \
  1530.     bison colordiff diff patch enscript cp df dir du ln ls mkfifo mknod mv rm \
  1531.     touch vdir awk gperf grep grub indent less m4 sed shar date \
  1532.     tee who texindex cat csplit cut expand fmt fold head \
  1533.     md5sum nl od paste pr ptx sha1sum sort split tac tail tr unexpand \
  1534.     uniq wc ldd bash id irb mkdir rmdir wget curl; do
  1535.     have $i && complete -F _longopt -o filenames $i
  1536. done
  1537.  
  1538. # These commands do not use filenames, so '-o filenames' is not needed.
  1539. for i in env netstat seq uname units; do
  1540.     have $i && complete -F _longopt -o default $i
  1541. done
  1542. unset i
  1543.  
  1544. _filedir_xspec()
  1545. {
  1546.     local IFS cur xspec
  1547.  
  1548.     IFS=$'\t\n'
  1549.     COMPREPLY=()
  1550.     _get_comp_words_by_ref cur
  1551.  
  1552.     _expand || return 0
  1553.  
  1554.     # get first exclusion compspec that matches this command
  1555.     xspec=$( awk "/^complete[ \t]+.*[ \t]${1##*/}([ \t]|\$)/ { print \$0; exit }" \
  1556.         "$BASH_COMPLETION" )
  1557.     # prune to leave nothing but the -X spec
  1558.     xspec=${xspec#*-X }
  1559.     xspec=${xspec%% *}
  1560.  
  1561.     local -a toks
  1562.     local tmp
  1563.  
  1564.     toks=( ${toks[@]-} $(
  1565.         compgen -d -- "$(quote_readline "$cur")" | {
  1566.         while read -r tmp; do
  1567.             # see long TODO comment in _filedir() --David
  1568.             printf '%s\n' $tmp
  1569.         done
  1570.         }
  1571.         ))
  1572.  
  1573.     toks=( ${toks[@]-} $(
  1574.         eval compgen -f -X "$xspec" -- "\$(quote_readline "\$cur")" | {
  1575.         while read -r tmp; do
  1576.             [ -n $tmp ] && printf '%s\n' $tmp
  1577.         done
  1578.         }
  1579.         ))
  1580.  
  1581.     COMPREPLY=( "${toks[@]}" )
  1582. }
  1583. list=( $( sed -ne '/^# START exclude/,/^# FINISH exclude/p' "$BASH_COMPLETION" | \
  1584.     # read exclusion compspecs
  1585.     (
  1586.     while read line
  1587.     do
  1588.         # ignore compspecs that are commented out
  1589.         if [ "${line#\#}" != "$line" ]; then continue; fi
  1590.         line=${line%# START exclude*}
  1591.         line=${line%# FINISH exclude*}
  1592.         line=${line##*\'}
  1593.         list=( "${list[@]}" $line )
  1594.     done
  1595.     printf '%s ' "${list[@]}"
  1596.     )
  1597.     ) )
  1598. # remove previous compspecs
  1599. if [ ${#list[@]} -gt 0 ]; then
  1600.     eval complete -r ${list[@]}
  1601.     # install new compspecs
  1602.     eval complete -F _filedir_xspec -o filenames "${list[@]}"
  1603. fi
  1604. unset list
  1605.  
  1606. # source completion directory definitions
  1607. if [[ -d $BASH_COMPLETION_COMPAT_DIR && -r $BASH_COMPLETION_COMPAT_DIR && \
  1608.     -x $BASH_COMPLETION_COMPAT_DIR ]]; then
  1609.     for i in $(LC_ALL=C command ls "$BASH_COMPLETION_COMPAT_DIR"); do
  1610.         i=$BASH_COMPLETION_COMPAT_DIR/$i
  1611.         [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) \
  1612.             && ( -f $i || -h $i ) && -r $i ]] && . "$i"
  1613.     done
  1614. fi
  1615. if [[ $BASH_COMPLETION_DIR != $BASH_COMPLETION_COMPAT_DIR && \
  1616.     -d $BASH_COMPLETION_DIR && -r $BASH_COMPLETION_DIR && \
  1617.     -x $BASH_COMPLETION_DIR ]]; then
  1618.     for i in $(LC_ALL=C command ls "$BASH_COMPLETION_DIR"); do
  1619.         i=$BASH_COMPLETION_DIR/$i
  1620.         [[ ${i##*/} != @(*~|*.bak|*.swp|\#*\#|*.dpkg*|*.rpm@(orig|new|save)) \
  1621.             && ( -f $i || -h $i ) && -r $i ]] && . "$i"
  1622.     done
  1623. fi
  1624. unset i
  1625.  
  1626. # source user completion file
  1627. [[ $BASH_COMPLETION != ~/.bash_completion && -r ~/.bash_completion ]] \
  1628.     && . ~/.bash_completion
  1629. unset -f have
  1630. unset UNAME USERLAND have
  1631.  
  1632. set $BASH_COMPLETION_ORIGINAL_V_VALUE
  1633. unset BASH_COMPLETION_ORIGINAL_V_VALUE
  1634.  
  1635. # Local variables:
  1636. # mode: shell-script
  1637. # sh-basic-offset: 4
  1638. # sh-indent-comment: t
  1639. # indent-tabs-mode: nil
  1640. # End:
  1641. # ex: ts=4 sw=4 et filetype=sh
  1642.